//
//  FLUploadModule.m
//  FLBaseWorkModule_iOS
//
//  Created by 魏延龙 on 2020/6/29.
//

#import "FLUploadModule.h"
#import <AliyunOSSiOS/OSSService.h>

#pragma mark aliyun配置
#define OSS_BUCKET_PUBLIC               @"ai-stable-doc"                              // bucket名称
#define OSS_BUCKET_PRIVATE              @"ai-stable-doc"                              // bucket名称
#define OSS_ENDPOINT                    @"http://oss-cn-shanghai.aliyuncs.com"        // 访问的阿里云endpoint

@interface FLUploadModule()

@property (nonatomic, strong) OSSClient *client;
@property (nonatomic, strong) OSSPutObjectRequest *normalUploadRequest;

@end
@implementation FLUploadModule
+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    static id sharedManager = nil;
    dispatch_once(&onceToken, ^{
        sharedManager = [[[self class] alloc] init];
    });
    return sharedManager;
}

// 可以放到appdelegate 中初始化
-(void)initClient {
    id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
        OSSFederationToken * token = [[OSSFederationToken alloc] init];
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        // 自动更新token的方式 
//        [WebDataAccessor getStsInfoWithBucket:OSS_BUCKET_PUBLIC durationSecond:3600 callBack:^(NSInteger code,id response, NSString *err, id stateObj) {
//            if (code == CODE_SUCCESS) {
//                NSString *accessKeyId = response[@"accessKeyId"];
//                NSString *accessKeySecret = response[@"accessKeySecret"];
//                NSString *expiration = response[@"expiration"];
//                NSString *securityToken = response[@"securityToken"];
//                NSLog(@"accessKeyId:%@-accessKeySecret:%@-expiration:%@-securityToken:%@",accessKeyId,accessKeySecret,expiration,securityToken);
//                token.tAccessKey = accessKeyId;
//                token.tSecretKey = accessKeySecret;
//                token.tToken = securityToken;
//                token.expirationTimeInGMTFormat = expiration;
//                dispatch_semaphore_signal(semaphore);
//            } else {
//              dispatch_semaphore_signal(semaphore);
//            }
//        } stateObj:nil];
    
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        return token;
    }] ;
    OSSClientConfiguration *cfg = [[OSSClientConfiguration alloc] init];
    cfg.maxRetryCount = 3;
    cfg.timeoutIntervalForRequest = 15;
    cfg.isHttpdnsEnable = NO;
    cfg.crc64Verifiable = YES;
    
    self.client = [[OSSClient alloc] initWithEndpoint:OSS_ENDPOINT credentialProvider:credential clientConfiguration:cfg];
    
}

-(NSString *)splitRecordFileNameWithTaskUid:(NSString *)taskuid fileName:(NSString *)fileName {
    //环境_客户端_时间_taskuid_fileName.mp3
    //debug_iOS_20200707_taskUid_name.mp3
    NSString *env;
    #ifdef DEBUG
    env = @"debug";
    #else
    env = @"release";
    #endif
    NSString *client = @"iOS";
    NSDate *currentDate = [NSDate date];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyyMMdd"];
    NSString *time = [dateFormatter stringFromDate:currentDate];
    NSString *name = [NSString stringWithFormat:@"%@_%@_%@_%@_%@.mp3",env,client,time,taskuid,fileName];
    return name;
}

-(NSString *)splitRemoteUrlWithName:(NSString *)fileName {
    NSString *url = [NSString stringWithFormat:@"https://%@%@%@",OSS_BUCKET_PRIVATE,@".oss-cn-shanghai.aliyuncs.com/",fileName];
    return url;
}

// 取消上传
- (void)normalRequestCancel
{
    if (_normalUploadRequest) {
        [_normalUploadRequest cancel];
    }
}

// 本地文件上传
-(void)uploadLocalFile:(NSString *)filePath objectKey:(NSString *)objectKey success:(void (^)(NSString *fileUrl))success failure:(void (^)(NSError *error))failure progress:(void (^)(CGFloat progress))progress {
    if (![objectKey oss_isNotEmpty]) {
        NSError *error = [NSError errorWithDomain:NSInvalidArgumentException code:0 userInfo:@{NSLocalizedDescriptionKey: @"objectKey should not be nil"}];
        if (failure) {
            failure(error);
        }
        return;
    }
    _normalUploadRequest = [OSSPutObjectRequest new];
    _normalUploadRequest.bucketName = OSS_BUCKET_PRIVATE;
    _normalUploadRequest.objectKey = objectKey;
    _normalUploadRequest.uploadingFileURL = [NSURL fileURLWithPath:filePath];
    _normalUploadRequest.isAuthenticationRequired = YES;
    _normalUploadRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
        float value = 1.f * totalByteSent / totalBytesExpectedToSend;
        if (progress) {
            progress(value);
        }
    };
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        __strong typeof(self) strongSelf = weakSelf;
        OSSTask * task = [strongSelf.client putObject:strongSelf.normalUploadRequest];
        [task continueWithBlock:^id(OSSTask *task) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (task.error) {
                    if (failure) {
                        failure(task.error);
                    }
                    [strongSelf writeLog:objectKey];
                } else {
                    NSString *url = [strongSelf splitRemoteUrlWithName:objectKey];
                    if (success) {
                        success(url);
                    }
                }
            });
            
            return nil;
        }];
    });
}

// NSData上传
-(void)uploadData:(NSData *)data objectKey:(NSString *)objectKey success:(void (^)(NSString *fileUrl))success failure:(void (^)(NSError *error))failure progress:(void (^)(CGFloat progress))progress {
    if (![objectKey oss_isNotEmpty]) {
        NSError *error = [NSError errorWithDomain:NSInvalidArgumentException code:0 userInfo:@{NSLocalizedDescriptionKey: @"objectKey should not be nil"}];
        if (failure) {
            failure(error);
        }
        return;
    }
    _normalUploadRequest = [OSSPutObjectRequest new];
    _normalUploadRequest.bucketName = OSS_BUCKET_PRIVATE;
    _normalUploadRequest.objectKey = objectKey;
    _normalUploadRequest.uploadingData = data;
    _normalUploadRequest.isAuthenticationRequired = YES;
    _normalUploadRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
        float value = 1.f * totalByteSent / totalBytesExpectedToSend;
        if (progress) {
            progress(value);
        }
    };
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        __strong typeof(self) strongSelf = weakSelf;
        OSSTask * task = [strongSelf.client putObject:strongSelf.normalUploadRequest];
        [task continueWithBlock:^id(OSSTask *task) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (task.error) {
                    if (failure) {
                        failure(task.error);
                    }
                    [strongSelf writeLog:objectKey];
                } else {
                    NSString *url = [strongSelf splitRemoteUrlWithName:objectKey];
                    if (success) {
                        success(url);
                    }
                }
            });
            
            return nil;
        }];
    });
}

// 大文件上传
- (void)uploadBigFile:(NSString *)filePath objectKey:(NSString *)objectKey success:(void (^)(NSString *fileUrl))success failure:(void (^)(NSError *error))failure progress:(void (^)(CGFloat progress))progress {
    if (![objectKey oss_isNotEmpty]) {
        NSError *error = [NSError errorWithDomain:NSInvalidArgumentException code:0 userInfo:@{NSLocalizedDescriptionKey: @"objectKey should not be nil"}];
        if (failure) {
            failure(error);
        }
        return;
    }
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        __strong typeof(self) strongSelf = weakSelf;
        // 获取沙盒的cache路径
        NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
        
        OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];
        resumableUpload.bucketName = OSS_BUCKET_PRIVATE;                                    // 设置bucket名称
        resumableUpload.objectKey = objectKey;                                              // 设置object key
        resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:filePath];                // 设置要上传的文件url
        resumableUpload.contentType = @"application/octet-stream";                          // 设置content-type
        resumableUpload.partSize = 102400;                                                  // 设置分片大小
        resumableUpload.recordDirectoryPath = cachesDir;                                    // 设置分片信息的本地存储路径
        
        // 设置metadata
        resumableUpload.completeMetaHeader = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil];
        
        // 设置上传进度回调
        resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
            float value = 1.f * totalByteSent / totalBytesExpectedToSend;
            if (progress) {
                progress(value);
            }
            NSLog(@"progress: %lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
        };
        
        OSSTask * resumeTask = [strongSelf.client resumableUpload:resumableUpload];
        [resumeTask waitUntilFinished];                             // 阻塞当前线程直到上传任务完成
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (resumeTask.result) {
                NSString *url = [strongSelf splitRemoteUrlWithName:objectKey];
                if (success) {
                    success(url);
                }
            } else {
                if (failure) {
                    failure(resumeTask.error);
                }
                [strongSelf writeLog:objectKey];
            }
        });
    });
}

-(void)writeLog:(NSString *)fileName {
    
}
@end
